package org.sundatagroup.aurora.monitor.controller;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;
import org.sundatagroup.aurora.core.service.querier.QuerierCenter;
import org.sundatagroup.aurora.monitor.config.IMonitor;
import org.sundatagroup.aurora.monitor.service.MonitorService;
import org.sundatagroup.aurora.show.controller.DisplayStatusEndpoint;
import org.sundatagroup.aurora.show.service.ScreenStatusService;

import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.JsonSyntaxException;

/**
 * <p>从监控前端 websocket 发来的数据
 * </p>
 * 
 * @version 0.2.0
 * <p>从该版本开始,
 * 这里只接收数据, 不处理发送数据. 发送数据的方法已经拆分到 {@link MonitorWebSocketController} 中
 * </p>
 * 
 * @author CharlesChen
 * @author Zdream
 * @date 2018-05-28
 * @since 0.1.1
 */
@Component
public class MonitorEndPoint extends TextWebSocketHandler
		implements IMonitor {
    private final static Logger LOGGER = LoggerFactory.getLogger(DisplayStatusEndpoint.class);
    
    private static JsonParser parser = new JsonParser();
    
    @Autowired
    ScreenStatusService statusQuerier;
    
    @Autowired
    MonitorWebSocketController sender;
	
	@Autowired
	QuerierCenter qrCenter;
	
	@Autowired
	MonitorService msv;

    /**
     * WebSocket链接建立时
     * @param session
     * @throws Exception
     */
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        LOGGER.info(session.getId() + " 已连接监控区");
        msv.registerMonitor(session);
    }

    /**
     * 链接关闭时
     * @param session
     * @param status
     * @throws Exception
     */
    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        LOGGER.info(session.getId() + " 断开监控区");
        msv.removeMonitor(session);
    }

    /**
     * 链接出错
     * @param session
     * @param exception
     * @throws Exception
     */
    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        LOGGER.error("产生错误: #" + session.getId(), exception);
    }

    /**
     * 收到浏览器发来的消息时
     * @param session
     * @param message 文本消息
     * @throws JsonSyntaxException
     */
    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        try {
            JsonObject jsonObj = parser.parse(message.getPayload()).getAsJsonObject();
            String messageStr = jsonObj.get("type").getAsString();
            
            switch (messageStr) {
                case "/status/sysnc":
                	sender.allStatus(session);
                    break;
                case "/playList/assign":
                	handlePlayListAssign(session, jsonObj.get("data"));
                    break;
                default:
                	if (messageStr.startsWith("/query/")) {
                		handleQuery(session, messageStr, jsonObj.get("data").getAsJsonObject());
                	}
                	break;
            }
        } catch (JsonSyntaxException e) {
            e.printStackTrace();
        }
    }
    
    /**
     * <p>处理指派播放列表的请求
     * <p>版本 0.2.0 只处理已有 playList 的情况. 即 {@code data.} 
     * </p>
     * @param session
     * @param data
     *   请求数据
     * @throws IllegalArgumentException
     *   当 data 不为 JsonObject 时
     * @since 0.2.0
     */
    private void handlePlayListAssign(WebSocketSession session, JsonElement data) {
    	if (!data.isJsonObject()) {
    		throw new IllegalArgumentException("请求数据: " + data + " 不符合要求");
    	}
    	JsonObject jo = data.getAsJsonObject();
    	
    	String sid = jo.get("sid").getAsString();
    	int lid = jo.get("playList").getAsInt(); // v0.2.0
    	msv.updateScreenPlayList(sid, lid);
    }
    
    /**
     * 处理通用查询
     * @param session
     * @param type
     * @param data
     */
    public void handleQuery(WebSocketSession session, String type, JsonObject data) {
    	JsonElement je = qrCenter.query(ID, type, data);
    	
    	if (je != null) {
    		sender.queryReturn(session, type.replace("query", "query-return"), je);
    	} else {
    		sender.queryReturnFall(session, type.replace("query", "query-return"));
    	}
    }
}
